# coding: utf-8
#	Magic comment en 1a línia --> strings són UTF-8 i no Ascii (així podem posar accents: àèìòù,áéíóú)
#!/usr/bin/env ruby -w
#	Opcions:-w=Activar Warnings. -KU=$KCODE = "U" --> strings són UTF-8, NO va en Ruby 1.9 !

### Compara calendaris en format iCalendar. 
### Fet a partir de csv2ical.rb (http://github.com/jasonmclaren/csv2ical).
### Author: Joan Ramió.
### Date: 3/02/2013

require 'icalendar'
require 'csv'

    $myname = "ical_show"
    puts "#{$myname}: Mostra info de calendaris en format iCalendar."
    $cal1 = ""
    Itm = Struct.new(:type, :num)

    if ARGV[0] != nil then $cal1 = ARGV[0] end;
    if $cal1.size < 1 then puts "Error: No files specified. Usage is: #{$myname} icalendar.ics"; exit; end
    if !File.exist?($cal1) then puts "Error: File '#{$cal1}' does not exist."; exit; end
       
    f1 = File.open($cal1)
    cals1 = Icalendar.parse(f1)

    if cals1.size != 1 then puts "ERROR: Hi ha varios calendaris en fitxer."; exit; end
    ca1 = cals1.first
    tot = ca1.events.size   	    
    tbl = Hash.new
    # Insert known fields in the desired output order
    ['summary', 'dtstart', 'dtend', 'location', 'description'].each { |prop|
	tbl[prop] = Itm.new
	tbl[prop].type = prop[0, 2] == "dt" ? "DateTime" : "String"
	tbl[prop].num = 0    	    
    }

puts "[#{$myname}] - calendar '#{$cal1}' has #{tot} events."
ca1.events.each { |ev1|
	ev1.properties.each { |prop| # [0]=nom, [1]=valor
		if !tbl.has_key?(prop[0]) then
			tbl[prop[0]] = Itm.new
			tbl[prop[0]].type = prop[1].class.name
			tbl[prop[0]].num = 0
		else
			# Compare first 4 chars of type so 'DateTime' is the same as 'Date'
			if tbl[prop[0]].type[0, 4] != prop[1].class.name[0, 4] then puts "ERROR: Field '#{prop[0]}' type is '#{tbl[prop[0]].type}' but found '#{prop[1].class.name}' in event '#{ev1.summary}'"; exit; end
		end
	case(prop[1].class.name) 
	when "String"      then if !prop[1].strip.empty?      then tbl[prop[0]].num += 1 end  
	when "DateTime"    then if !prop[1].to_s.strip.empty? then tbl[prop[0]].num += 1 end
	when "Date"        then if !prop[1].to_s.strip.empty? then tbl[prop[0]].num += 1 end
	when "Fixnum"      then if !prop[1].to_s.strip.empty? then tbl[prop[0]].num += 1 end
	when "Array"       then if !prop[1].empty?            then tbl[prop[0]].num += 1 end
	when "URI::MailTo" then if !prop[1].to.strip.empty?   then tbl[prop[0]].num += 1 end
	else puts("ERROR: Field '#{prop[0]}' has an unknown type '#{prop[1].class.name}'."); exit
	end
	} 
}

puts "[#{$myname}] - counting fields found in #{tot} events:"
tbl.each { |key, value|
	puts "(#{value.type}) '#{key}': #{value.num}"
}

# Obligatory fields in all events
['summary', 'dtstart', 'dtend', 'uid', 'sequence', 'created', 'last_modified'].each { |prop|
	if tbl.has_key?(prop) then num = tbl[prop].num else num = 0 end
	if num < tot then puts "WARNING: #{tot- num} events without '#{prop}'." end
}	
# Forbidden fields in all events
['attach', 'recurrence_id'].each { |prop|
	if tbl.has_key?(prop) then num = tbl[prop].num else num = 0 end
	if num > 0 then puts "WARNING: #{num} events with '#{prop}'." end
}	
# Meetings
if tbl.has_key?('organizer') then num = tbl['organizer'].num else num = 0 end
if tbl.has_key?('attendee') then num2 = tbl['attendee'].num else num2 = 0 end
if num != num2 then puts "WARNING: #{num- num2} meetings(they have 'organizer') without 'attendee'." end

puts "[#{$myname}] - showed #{tot} events."

